package com.du.method;

import com.du.entity.ConvertParam;
import org.yaml.snakeyaml.Yaml;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @Desc :
 * @Author: shuangdu
 * @date : 2024/4/29
 */
@SuppressWarnings("unchecked")
public class YmlToProperties implements ConvertMethod{

    public final String parseRegexAT = "@";
    public final String replacementAT = "_myConvertAT_";

    public final String parseRegexPercent = "%";
    public final String replacementPercent = "_myConvertPercent_";

    @Override
    public String parse() {
        ConvertParam param = ConvertContext.holder.getParam();
        String source = param.getSourceText()
                .replaceAll("\\t", " ")
                .replaceAll(parseRegexAT, replacementAT)
                .replaceAll(parseRegexPercent, replacementPercent);

        Yaml yaml = new Yaml();
        Map<String, Object> yamlData = yaml.load(source);

        Map<String, String> properties = new LinkedHashMap<>();
        resolveYaml(properties, yamlData, "");

        return toProperties(properties);
    }

    private String toProperties(Map<String, String> properties) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            sb.append(entry.getKey())
                    .append("=")
                    .append(entry.getValue())
                    .append("\n");
        }
        return sb.toString().replaceAll(replacementAT, parseRegexAT).replaceAll(replacementPercent, parseRegexPercent);
    }

    private void resolveYaml(Map<String, String> properties, Map<String, Object> yamlData, String block) {
        for (Map.Entry<String, Object> entry : yamlData.entrySet()) {
            String key;
            if (block.equals("")) {
                key = entry.getKey();
            } else {
                key = block + "." + entry.getKey();
            }
            if (entry.getValue() instanceof Map) {
                resolveYaml(properties, (Map<String, Object>)entry.getValue(), key);
            } else {
                properties.put(key, String.valueOf(Optional.ofNullable(entry.getValue()).orElse("")));
            }
        }
    }
}
